home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / ungepackte_daten / 1994 / 8 / 05 / term-4.0-source.lha / termFastMacroWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-17  |  20.2 KB  |  1,029 lines

  1. /*
  2. **    termFastMacroWindow.c
  3. **
  4. **    Fast! macro window support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Window border scroller. */
  13.  
  14. enum    {    GAD_SCROLLER = 10000,GAD_UP,GAD_DOWN };
  15.  
  16.     /* The arrow image height. */
  17.  
  18. #define ARROW_HEIGHT    11
  19.  
  20.     /* Pack two words into a long. */
  21.  
  22. #define PACK_ULONG(a,b)    (((ULONG)(a)) << 16 | b)
  23.  
  24.     /* Gadget extension. */
  25.  
  26. struct ButtonInfo
  27. {
  28.     struct Image    *ButtonImage;
  29.     STRPTR         ButtonCommand;
  30.     LONG         NumChars;
  31. };
  32.  
  33.     /* A private button gadget attribute. */
  34.  
  35. #define BGA_Command    (TAG_USER + 1)
  36.  
  37.     /* Private button gadget class. */
  38.  
  39. STATIC struct IClass        *ButtonClass;
  40.  
  41.     /* Window border scroller. */
  42.  
  43. STATIC struct Gadget        *Scroller,
  44.                 *UpArrow,
  45.                 *DownArrow;
  46.  
  47.     /* Width of the window border scroller. */
  48.  
  49. STATIC UWORD             RightBorderWidth;
  50.  
  51.     /* Scroller arrow imagery. */
  52.  
  53. STATIC struct Image        *UpImage,
  54.                 *DownImage;
  55.  
  56.     /* The window zoom box. */
  57.  
  58. STATIC struct IBox         WindowZoomBox = { -1,-1,-1,-1 };
  59.  
  60.     /* The fast macro buttons. */
  61.  
  62. STATIC struct Gadget        *Buttons;
  63.  
  64.     /* The first visible button and the number buttons
  65.      * visible in total.
  66.      */
  67.  
  68. STATIC LONG             ButtonTop,
  69.                  ButtonCount;
  70.  
  71.     /* RenderText():
  72.      *
  73.      *    Render the button text.
  74.      */
  75.  
  76. STATIC VOID __regargs
  77. RenderText(struct RastPort *RPort,struct GadgetInfo *GadgetInfo,struct Gadget *Gadget,LONG Len)
  78. {
  79.     UWORD     Width    = (GadgetInfo -> gi_Window -> Width - (GadgetInfo -> gi_Window -> BorderLeft + GadgetInfo -> gi_Window -> BorderRight + 4));
  80.     STRPTR     Label    = (STRPTR)Gadget -> GadgetText;
  81.     ULONG     State;
  82.  
  83.         /* Which state is the button in? */
  84.  
  85.     if(Gadget -> Flags & GFLG_SELECTED)
  86.         State = IDS_SELECTED;
  87.     else
  88.         State = IDS_NORMAL;
  89.  
  90.         /* Render the frame. */
  91.  
  92.     DoMethod(Gadget -> GadgetRender,IM_DRAWFRAME,RPort,PACK_ULONG(Gadget -> LeftEdge + 2,Gadget -> TopEdge),State,GadgetInfo -> gi_DrInfo,PACK_ULONG(Width,Gadget -> Height));
  93.  
  94.         /* Set the rendering pens. */
  95.  
  96.     SetDrMd(RPort,JAM1);
  97.  
  98.     if(State == IDS_SELECTED)
  99.         SetAPen(RPort,GadgetInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN]);
  100.     else
  101.         SetAPen(RPort,GadgetInfo -> gi_DrInfo -> dri_Pens[TEXTPEN]);
  102.  
  103.         /* Render the button label. */
  104.  
  105.     Move(RPort,Gadget -> LeftEdge + 4,Gadget -> TopEdge + (Gadget -> Height - GadgetInfo -> gi_DrInfo -> dri_Font -> tf_YSize) / 2 + GadgetInfo -> gi_DrInfo -> dri_Font -> tf_Baseline);
  106.     Text(RPort,Label,Len);
  107. }
  108.  
  109.     /* SetButton():
  110.      *
  111.      *    Set an aspect of the button.
  112.      */
  113.  
  114. STATIC ULONG __regargs
  115. SetButton(struct IClass *class,Object *object,struct opSet *SetInfo)
  116. {
  117.     struct ButtonInfo    *ButtonInfo = INST_DATA(class,object);
  118.     struct TagItem        *Tag;
  119.  
  120.         /* Pick up the button command. */
  121.  
  122.     if(Tag = FindTagItem(BGA_Command,SetInfo -> ops_AttrList))
  123.         ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  124.  
  125.         /* Label text changed? */
  126.  
  127.     if(Tag = FindTagItem(GA_Text,SetInfo -> ops_AttrList))
  128.     {
  129.         struct RastPort    *RPort    = ObtainGIRPort(SetInfo -> ops_GInfo);
  130.         STRPTR         Label    = (STRPTR)Tag -> ti_Data;
  131.         LONG         Len    = strlen(Label),
  132.                  Width    = ((struct Gadget *)object) -> Width - 8;
  133.  
  134.             /* Install the new label text. */
  135.  
  136.         ((struct Gadget *)object) -> GadgetText = (struct IntuiText *)Label;
  137.  
  138.         if(RPort)
  139.         {
  140.                 /* Determine label length. */
  141.  
  142.             while(Len > 0 && TextLength(RPort,Label,Len) > Width)
  143.                 Len--;
  144.  
  145.             ButtonInfo -> NumChars = Len;
  146.  
  147.             RenderText(RPort,SetInfo -> ops_GInfo,(struct Gadget *)object,Len);
  148.  
  149.             ReleaseGIRPort(RPort);
  150.         }
  151.  
  152.         return(1);
  153.     }
  154.     else
  155.         return(DoSuperMethodA(class,object,(Msg)SetInfo));
  156. }
  157.  
  158.     /* RenderButton():
  159.      *
  160.      *    Render the button label.
  161.      */
  162.  
  163. STATIC ULONG __regargs
  164. RenderButton(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  165. {
  166.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  167.  
  168.         /* No label length calculated yet? */
  169.  
  170.     if(!ButtonInfo -> NumChars)
  171.     {
  172.         STRPTR    Label    = (STRPTR)((struct Gadget *)object) -> GadgetText;
  173.         LONG    Len    = strlen(Label),
  174.             Width    = ((struct Gadget *)object) -> Width - 8;
  175.  
  176.         while(Len > 0 && TextLength(RenderInfo -> gpr_RPort,Label,Len) > Width)
  177.             Len--;
  178.  
  179.         ButtonInfo -> NumChars = Len;
  180.     }
  181.  
  182.     RenderText(RenderInfo -> gpr_RPort,RenderInfo -> gpr_GInfo,(struct Gadget *)object,ButtonInfo -> NumChars);
  183.  
  184.     return(1);
  185. }
  186.  
  187.     /* FreeButton():
  188.      *
  189.      *    Free a button gadget object.
  190.      */
  191.  
  192. STATIC ULONG __regargs
  193. FreeButton(struct IClass *class,Object *object,Msg msg)
  194. {
  195.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  196.  
  197.     if(ButtonInfo -> ButtonImage)
  198.         DisposeObject(ButtonInfo -> ButtonImage);
  199.  
  200.     return(DoSuperMethodA(class,object,msg));
  201. }
  202.  
  203.     /* NewButton():
  204.      *
  205.      *    Create a new button object.
  206.      */
  207.  
  208. STATIC ULONG __regargs
  209. NewButton(struct IClass *class,Object *object,struct opSet *SetMethod)
  210. {
  211.     LONG         Width,
  212.              Height;
  213.     struct TagItem    *Tag;
  214.     struct Gadget    *NewGadget = NULL;
  215.  
  216.         /* Determine object width. */
  217.  
  218.     if(Tag = FindTagItem(GA_Width,SetMethod -> ops_AttrList))
  219.         Width = Tag -> ti_Data;
  220.     else
  221.         Width = 0;
  222.  
  223.         /* Determine object height. */
  224.  
  225.     if(Tag = FindTagItem(GA_Height,SetMethod -> ops_AttrList))
  226.         Height = Tag -> ti_Data;
  227.     else
  228.         Height = 0;
  229.  
  230.         /* Proper dimensions? */
  231.  
  232.     if(Width && Height)
  233.     {
  234.         struct Image *ButtonImage;
  235.  
  236.             /* Create a button frame. */
  237.  
  238.         if(ButtonImage = NewObject(NULL,"frameiclass",
  239.             IA_Width,    Width,
  240.             IA_Height,    Height,
  241.         TAG_DONE))
  242.         {
  243.             struct TagItem    *OldTags = SetMethod -> ops_AttrList,
  244.                      NewTags[2];
  245.  
  246.                 /* Add new tag values. */
  247.  
  248.             NewTags[0] . ti_Tag    = GA_Image;
  249.             NewTags[0] . ti_Data    = (ULONG)ButtonImage;
  250.             NewTags[1] . ti_Tag    = TAG_MORE;
  251.             NewTags[1] . ti_Data    = (ULONG)OldTags;
  252.  
  253.             SetMethod -> ops_AttrList = NewTags;
  254.  
  255.                 /* Create new object. */
  256.  
  257.             if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
  258.             {
  259.                 struct ButtonInfo *ButtonInfo = INST_DATA(class,NewGadget);
  260.  
  261.                     /* Clear the number of characters displayed,
  262.                      * the first rendering call will adjust it.
  263.                      */
  264.  
  265.                 ButtonInfo -> NumChars = 0;
  266.  
  267.                     /* Install the corresponding command. */
  268.  
  269.                 if(Tag = FindTagItem(BGA_Command,OldTags))
  270.                     ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  271.  
  272.                     /* Remember the frame image. */
  273.  
  274.                 ButtonInfo -> ButtonImage = ButtonImage;
  275.  
  276.                     /* Restore the tags. */
  277.  
  278.                 SetMethod -> ops_AttrList = OldTags;
  279.             }
  280.             else
  281.                 DisposeObject(ButtonImage);
  282.         }
  283.     }
  284.  
  285.     return((ULONG)NewGadget);
  286. }
  287.  
  288.     /* HitButton():
  289.      *
  290.      *    Check to see whether a point is within the button frame.
  291.      */
  292.  
  293. STATIC ULONG __regargs
  294. HitButton(struct IClass *class,Object *object,struct gpHitTest *HitInfo)
  295. {
  296.     struct ButtonInfo    *ButtonInfo    = INST_DATA(class,object);
  297.     ULONG            *Spot        = (ULONG *)&HitInfo -> gpht_Mouse,
  298.                 *Size        = (ULONG *)&((struct Gadget *)object) -> Width;
  299.  
  300.     return(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,*Spot,*Size));
  301. }
  302.  
  303.     /* HandleButton():
  304.      *
  305.      *    Handle button input.
  306.      */
  307.  
  308. STATIC ULONG __regargs
  309. HandleButton(struct IClass *class,Object *object,struct gpInput *InputInfo)
  310. {
  311.     ULONG Result = GMR_MEACTIVE;
  312.  
  313.         /* Only mouse events are supported. */
  314.  
  315.     if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
  316.     {
  317.         struct ButtonInfo    *ButtonInfo    = INST_DATA(class,object);
  318.         struct Gadget        *Button        = (struct Gadget *)object;
  319.         BYTE             Redraw;
  320.  
  321.             /* Selection cancelled or no command available? */
  322.  
  323.         if(InputInfo -> gpi_IEvent -> ie_Code == IECODE_RBUTTON || !ButtonInfo -> ButtonCommand[0])
  324.         {
  325.             *InputInfo -> gpi_Termination = 1;
  326.  
  327.             Result = GMR_REUSE | GMR_VERIFY;
  328.  
  329.             if(Button -> Flags & GFLG_SELECTED)
  330.             {
  331.                 Button -> Flags &= ~GFLG_SELECTED;
  332.  
  333.                 Redraw = TRUE;
  334.             }
  335.             else
  336.                 Redraw = FALSE;
  337.         }
  338.         else
  339.         {
  340.                 /* Select button released? */
  341.  
  342.             if(InputInfo -> gpi_IEvent -> ie_Code == (IECODE_LBUTTON | IECODE_UP_PREFIX))
  343.             {
  344.                 if(Button -> Flags & GFLG_SELECTED)
  345.                 {
  346.                     *InputInfo -> gpi_Termination = 0;
  347.  
  348.                     Result = GMR_NOREUSE | GMR_VERIFY;
  349.  
  350.                     Button -> Flags &= ~GFLG_SELECTED;
  351.  
  352.                     Redraw = TRUE;
  353.                 }
  354.                 else
  355.                 {
  356.                     *InputInfo -> gpi_Termination = 1;
  357.  
  358.                     Result = GMR_REUSE | GMR_VERIFY;
  359.  
  360.                     Redraw = FALSE;
  361.                 }
  362.             }
  363.             else
  364.             {
  365.                 ULONG *Size = (ULONG *)&Button -> Width;
  366.  
  367.                     /* Hit inside the boundaries? */
  368.  
  369.                 if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),*Size))
  370.                 {
  371.                     if(Button -> Flags & GFLG_SELECTED)
  372.                         Redraw = FALSE;
  373.                     else
  374.                     {
  375.                         Button -> Flags |= GFLG_SELECTED;
  376.  
  377.                         Redraw = TRUE;
  378.                     }
  379.                 }
  380.                 else
  381.                 {
  382.                     if(Button -> Flags & GFLG_SELECTED)
  383.                     {
  384.                         Button -> Flags &= ~GFLG_SELECTED;
  385.  
  386.                         Redraw = TRUE;
  387.                     }
  388.                     else
  389.                         Redraw = FALSE;
  390.                 }
  391.             }
  392.         }
  393.  
  394.             /* Redraw the object? */
  395.  
  396.         if(Redraw)
  397.         {
  398.             struct RastPort *RPort;
  399.  
  400.             if(RPort = ObtainGIRPort(InputInfo -> gpi_GInfo))
  401.             {
  402.                 RenderText(RPort,InputInfo -> gpi_GInfo,Button,ButtonInfo -> NumChars);
  403.  
  404.                 ReleaseGIRPort(RPort);
  405.             }
  406.         }
  407.     }
  408.  
  409.     return(Result);
  410. }
  411.  
  412.     /* ButtonDispatch():
  413.      *
  414.      *    The button gadget class dispatcher.
  415.      */
  416.  
  417. STATIC ULONG __saveds __asm
  418. ButtonDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  419. {
  420.         /* Select the message method. */
  421.  
  422.     switch(msg -> MethodID)
  423.     {
  424.         case OM_NEW:
  425.  
  426.             return(NewButton(class,object,(struct opSet *)msg));
  427.  
  428.         case OM_UPDATE:
  429.         case OM_SET:
  430.  
  431.             return(SetButton(class,object,(struct opSet *)msg));
  432.  
  433.         case OM_DISPOSE:
  434.  
  435.             return(FreeButton(class,object,msg));
  436.  
  437.         case GM_RENDER:
  438.  
  439.             return(RenderButton(class,object,(struct gpRender *)msg));
  440.  
  441.         case GM_HITTEST:
  442.  
  443.             return(HitButton(class,object,(struct gpHitTest *)msg));
  444.  
  445.         case GM_GOINACTIVE:
  446.  
  447.             return(0);
  448.  
  449.         case GM_GOACTIVE:
  450.  
  451.             return(GMR_MEACTIVE);
  452.  
  453.         case GM_HANDLEINPUT:
  454.  
  455.             return(HandleButton(class,object,(struct gpInput *)msg));
  456.  
  457.         default:
  458.  
  459.             return(DoSuperMethodA(class,object,msg));
  460.     }
  461. }
  462.  
  463.     /* FreeButtonClass(VOID):
  464.      *
  465.      *    Free private button gadget class.
  466.      */
  467.  
  468. STATIC VOID
  469. FreeButtonClass(VOID)
  470. {
  471.     if(ButtonClass)
  472.     {
  473.         FreeClass(ButtonClass);
  474.  
  475.         ButtonClass = NULL;
  476.     }
  477. }
  478.  
  479.     /* NewButtonClass(VOID):
  480.      *
  481.      *    Create private button gadget class.
  482.      */
  483.  
  484. STATIC BYTE
  485. NewButtonClass(VOID)
  486. {
  487.     if(ButtonClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct ButtonInfo),0))
  488.     {
  489.         ButtonClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ButtonDispatch;
  490.  
  491.         return(TRUE);
  492.     }
  493.     else
  494.         return(FALSE);
  495. }
  496.  
  497.     /* FastDeleteScroller(VOID):
  498.      *
  499.      *    Delete fast! macro window scroller.
  500.      */
  501.  
  502. STATIC VOID
  503. FastDeleteScroller(VOID)
  504. {
  505.     if(Scroller)
  506.     {
  507.         DisposeObject(Scroller);
  508.  
  509.         Scroller = NULL;
  510.     }
  511.  
  512.     if(UpArrow)
  513.     {
  514.         DisposeObject(UpArrow);
  515.  
  516.         UpArrow = NULL;
  517.     }
  518.  
  519.     if(DownArrow)
  520.     {
  521.         DisposeObject(DownArrow);
  522.  
  523.         DownArrow = NULL;
  524.     }
  525.  
  526.     if(UpImage)
  527.     {
  528.         DisposeObject(UpImage);
  529.  
  530.         UpImage = NULL;
  531.     }
  532.  
  533.     if(DownImage)
  534.     {
  535.         DisposeObject(DownImage);
  536.  
  537.         DownImage = NULL;
  538.     }
  539. }
  540.  
  541.     /* FastCreateScroller(struct Screen *Screen):
  542.      *
  543.      *    Create fast! macro window scroller.
  544.      */
  545.  
  546. STATIC BYTE __regargs
  547. FastCreateScroller(struct Screen *Screen)
  548. {
  549.     struct DrawInfo    *DrawInfo;
  550.     BYTE         Result = FALSE;
  551.  
  552.     if(DrawInfo = GetScreenDrawInfo(Screen))
  553.     {
  554.         LONG    SizeWidth,
  555.             SizeHeight;
  556.         UWORD    SizeType;
  557.  
  558.         if(Screen -> Flags & SCREENHIRES)
  559.         {
  560.             SizeWidth    = 18;
  561.             SizeHeight    = 10;
  562.  
  563.             SizeType    = SYSISIZE_MEDRES;
  564.         }
  565.         else
  566.         {
  567.             SizeWidth    = 13;
  568.             SizeHeight    = 11;
  569.  
  570.             SizeType    = SYSISIZE_LOWRES;
  571.         }
  572.  
  573.         RightBorderWidth = SizeWidth;
  574.  
  575.         if(UpImage = (struct Image *)NewObject(NULL,"sysiclass",
  576.             SYSIA_Size,    SizeType,
  577.             SYSIA_Which,    UPIMAGE,
  578.             SYSIA_DrawInfo,    DrawInfo,
  579.         TAG_DONE))
  580.         {
  581.             if(DownImage = (struct Image *)NewObject(NULL,"sysiclass",
  582.                 SYSIA_Size,    SizeType,
  583.                 SYSIA_Which,    DOWNIMAGE,
  584.                 SYSIA_DrawInfo,    DrawInfo,
  585.             TAG_DONE))
  586.             {
  587.                 if(Scroller = NewObject(NULL,"propgclass",
  588.                     GA_ID,        GAD_SCROLLER,
  589.  
  590.                     GA_Top,        Screen -> WBorTop + Screen -> Font -> ta_YSize + 2,
  591.                     GA_RelHeight,    -(Screen -> WBorTop + Screen -> Font -> ta_YSize + 2 + SizeHeight + 1 + 2 * ARROW_HEIGHT),
  592.                     GA_Width,    SizeWidth - 8,
  593.                     GA_RelRight,    -(SizeWidth - 5),
  594.  
  595.                     GA_Immediate,    TRUE,
  596.                     GA_FollowMouse,    TRUE,
  597.                     GA_RelVerify,    TRUE,
  598.                     GA_RightBorder,    TRUE,
  599.  
  600.                     PGA_Freedom,    FREEVERT,
  601.                     PGA_NewLook,    TRUE,
  602.                     PGA_Borderless,    TRUE,
  603.  
  604.                     PGA_Visible,    1,
  605.                     PGA_Total,    1,
  606.                 TAG_DONE))
  607.                 {
  608.                     STATIC struct TagItem ArrowMappings[] =
  609.                     {
  610.                         GA_ID,    GA_ID,
  611.                         TAG_END
  612.                     };
  613.  
  614.                     if(UpArrow = NewObject(NULL,"buttongclass",
  615.                         GA_ID,        GAD_UP,
  616.  
  617.                         GA_Image,    UpImage,
  618.                         GA_RelRight,    -(SizeWidth - 1),
  619.                         GA_RelBottom,    -(SizeHeight - 1 + 2 * ARROW_HEIGHT),
  620.                         GA_Height,    ARROW_HEIGHT,
  621.                         GA_Width,    SizeWidth,
  622.                         GA_Immediate,    TRUE,
  623.                         GA_RelVerify,    TRUE,
  624.                         GA_Previous,    Scroller,
  625.                         GA_RightBorder,    TRUE,
  626.  
  627.                         ICA_TARGET,    ICTARGET_IDCMP,
  628.                         ICA_MAP,    ArrowMappings,
  629.                     TAG_DONE))
  630.                     {
  631.                         if(DownArrow = NewObject(NULL,"buttongclass",
  632.                             GA_ID,        GAD_DOWN,
  633.  
  634.                             GA_Image,    DownImage,
  635.                             GA_RelRight,    -(SizeWidth - 1),
  636.                             GA_RelBottom,    -(SizeHeight - 1 + ARROW_HEIGHT),
  637.                             GA_Height,    ARROW_HEIGHT,
  638.                             GA_Width,    SizeWidth,
  639.                             GA_Immediate,    TRUE,
  640.                             GA_RelVerify,    TRUE,
  641.                             GA_Previous,    UpArrow,
  642.                             GA_RightBorder,    TRUE,
  643.  
  644.                             ICA_TARGET,    ICTARGET_IDCMP,
  645.                             ICA_MAP,    ArrowMappings,
  646.                         TAG_DONE))
  647.                             Result = TRUE;
  648.                     }
  649.                 }
  650.             }
  651.         }
  652.  
  653.         FreeScreenDrawInfo(Screen,DrawInfo);
  654.     }
  655.  
  656.     return(Result);
  657. }
  658.  
  659.     /* RefreshFastWindow(WORD FastWindowHeight):
  660.      *
  661.      *    Refresh the contents of the fast! macro window.
  662.      */
  663.  
  664. VOID __regargs
  665. RefreshFastWindow(BYTE FullRefresh)
  666. {
  667.     if(FastWindow)
  668.     {
  669.         LONG Count = (FastWindow -> Height - (FastWindow -> BorderTop + FastWindow -> BorderBottom + 1)) / (2 + UserFontHeight + 2 + 1);
  670.  
  671.         if(FullRefresh)
  672.             ButtonCount = 0;
  673.  
  674.         if(Count == ButtonCount && Buttons)
  675.         {
  676.             LONG NewTop;
  677.  
  678.             if(!GetAttr(PGA_Top,Scroller,(ULONG *)&NewTop))
  679.                 NewTop = 0;
  680.  
  681.             if(NewTop != ButtonTop)
  682.             {
  683.                 ButtonTop = NewTop;
  684.  
  685.                 Count = 0;
  686.  
  687.                 if(FastMacroList . lh_Head -> ln_Succ)
  688.                 {
  689.                     struct DrawInfo *DrawInfo;
  690.  
  691.                     if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  692.                     {
  693.                         struct MacroNode    *Node    = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  694.                         struct Gadget        *Button    = Buttons;
  695.  
  696.                         while(Count < ButtonCount && Node -> mn_Succ)
  697.                         {
  698.                             SetGadgetAttrs(Button,FastWindow,NULL,
  699.                                 GA_Text,    Node -> mn_Macro,
  700.                                 BGA_Command,    Node -> mn_Code,
  701.                             TAG_DONE);
  702.  
  703.                             Count++;
  704.  
  705.                             Button = Button -> NextGadget;
  706.  
  707.                             Node = Node -> mn_Succ;
  708.                         }
  709.  
  710.                         FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  711.                     }
  712.                 }
  713.             }
  714.         }
  715.         else
  716.         {
  717.             LONG Top = FastWindow -> BorderTop + 1;
  718.  
  719.             if(Buttons)
  720.             {
  721.                 struct Gadget    *Next = Buttons,
  722.                         *Button;
  723.  
  724.                 RemoveGList(FastWindow,Buttons,-1);
  725.  
  726.                 while(Button = Next)
  727.                 {
  728.                     Next = Button -> NextGadget;
  729.  
  730.                     DisposeObject(Button);
  731.                 }
  732.  
  733.                 Buttons = NULL;
  734.             }
  735.  
  736.             ButtonCount = Count;
  737.  
  738.             if(ButtonTop >= FastMacroCount)
  739.                 ButtonTop = FastMacroCount - ButtonCount;
  740.             else
  741.             {
  742.                 if(ButtonTop + ButtonCount > FastMacroCount)
  743.                     ButtonTop = FastMacroCount - ButtonCount;
  744.             }
  745.  
  746.             if(ButtonTop < 0)
  747.                 ButtonTop = 0;
  748.  
  749.             Count = 0;
  750.  
  751.             if(FastMacroList . lh_Head -> ln_Succ)
  752.             {
  753.                 struct DrawInfo *DrawInfo;
  754.  
  755.                 if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  756.                 {
  757.                     struct MacroNode    *Node        = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  758.                     LONG             Width        = FastWindow -> Width - (FastWindow -> BorderLeft + FastWindow -> BorderRight);
  759.                     struct Gadget        *Previous    = NULL,
  760.                                 *Button;
  761.  
  762.                     while(Count < ButtonCount && Node -> mn_Succ)
  763.                     {
  764.                         if(Button = NewObject(ButtonClass,NULL,
  765.                             GA_ID,        Count,
  766.  
  767.                             GA_Top,        Top,
  768.                             GA_Left,    FastWindow -> BorderLeft,
  769.  
  770.                             GA_Width,    Width,
  771.                             GA_Height,    (2 + UserFontHeight + 2),
  772.                             GA_RelVerify,    TRUE,
  773.  
  774.                             GA_DrawInfo,    DrawInfo,
  775.                             GA_Text,    Node -> mn_Macro,
  776.                             BGA_Command,    Node -> mn_Code,
  777.  
  778.                             Previous ? GA_Previous : TAG_IGNORE,Previous,
  779.                         TAG_DONE))
  780.                         {
  781.                             Top += 2 + UserFontHeight + 2 + 1;
  782.  
  783.                             Count++;
  784.  
  785.                             Previous = Button;
  786.  
  787.                             if(!Buttons)
  788.                                 Buttons = Button;
  789.  
  790.                             Node = Node -> mn_Succ;
  791.                         }
  792.                     }
  793.  
  794.                     FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  795.                 }
  796.             }
  797.  
  798.             if(Count)
  799.             {
  800.                 AddGList(FastWindow,Buttons,-1,-1,NULL);
  801.  
  802.                 RefreshGList(Buttons,FastWindow,NULL,-1);
  803.             }
  804.  
  805.             if(Top < FastWindow -> Height - (FastWindow -> BorderBottom + 1))
  806.             {
  807.                 SetAPen(FastWindow -> RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  808.  
  809.                 RectFill(FastWindow -> RPort,FastWindow -> BorderLeft,Top,FastWindow -> Width - (FastWindow -> BorderRight + 1),FastWindow -> Height - (FastWindow -> BorderBottom + 1));
  810.             }
  811.  
  812.             SetGadgetAttrs(Scroller,FastWindow,NULL,
  813.                 PGA_Top,    ButtonTop,
  814.                 PGA_Visible,    ButtonCount,
  815.                 PGA_Total,    FastMacroCount,
  816.             TAG_DONE);
  817.         }
  818.     }
  819. }
  820.  
  821.     /* CloseFastWindow():
  822.      *
  823.      *    Close the fast! macro window and free the associated resources.
  824.      */
  825.  
  826. VOID
  827. CloseFastWindow()
  828. {
  829.     CheckItem(MEN_FAST_MACROS_WINDOW,FALSE);
  830.  
  831.     if(Buttons)
  832.     {
  833.         struct Gadget    *Next = Buttons,
  834.                 *Button;
  835.  
  836.         RemoveGList(FastWindow,Buttons,-1);
  837.  
  838.         while(Button = Next)
  839.         {
  840.             Next = Button -> NextGadget;
  841.  
  842.             DisposeObject(Button);
  843.         }
  844.  
  845.         Buttons = NULL;
  846.     }
  847.  
  848.     if(FastWindow)
  849.     {
  850.         PutWindowInfo(WINDOW_FAST,FastWindow -> LeftEdge,FastWindow -> TopEdge,FastWindow -> Width,FastWindow -> Height);
  851.  
  852.         ClearMenuStrip(FastWindow);
  853.         CloseWindowSafely(FastWindow);
  854.  
  855.         FastWindow = NULL;
  856.     }
  857.  
  858.     FreeButtonClass();
  859. }
  860.  
  861.     /* OpenFastWindow():
  862.      *
  863.      *    Open the fast! macro window.
  864.      */
  865.  
  866. BYTE
  867. OpenFastWindow()
  868. {
  869.     if(NewButtonClass())
  870.     {
  871.         if(FastCreateScroller(Window -> WScreen))
  872.         {
  873.             LONG    Left    = 0,
  874.                 Top    = 0,
  875.                 Width    = Window -> WScreen -> WBorLeft + 2 + SZ_GetLen("####################") + 2 + RightBorderWidth,
  876.                 Height    = 0;
  877.  
  878.             GetWindowInfo(WINDOW_FAST,&Left,&Top,&Width,&Height,NULL,Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + 10 * (2 + UserFontHeight + 2 + 1) + Window -> WScreen -> WBorBottom);
  879.  
  880.             if(WindowZoomBox . Left == -1)
  881.             {
  882.                 WindowZoomBox . Left    = 0;
  883.                 WindowZoomBox . Top    = 0;
  884.                 WindowZoomBox . Width    = Width;
  885.                 WindowZoomBox . Height    = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1;
  886.             }
  887.  
  888.             if(FastWindow = OpenWindowTags(NULL,
  889.                 WA_Width,        Width,
  890.                 WA_Height,        Height,
  891.  
  892.                 WA_Left,        Left,
  893.                 WA_Top,            Top,
  894.  
  895.                 WA_DragBar,        TRUE,
  896.                 WA_DepthGadget,        TRUE,
  897.                 WA_CloseGadget,        TRUE,
  898.                 WA_RMBTrap,        TRUE,
  899.                 WA_Zoom,        &WindowZoomBox,
  900.                 WA_NoCareRefresh,    TRUE,
  901.                 WA_BackFill,        &BackfillHook,
  902.  
  903.                 WA_SizeGadget,        TRUE,
  904.  
  905.                 WA_MinWidth,        Width,
  906.                 WA_MaxWidth,        Width,
  907.  
  908.                 WA_MinHeight,        Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 2 * (2 + UserFontHeight + 2 + 1) + 1 + Window -> WScreen -> WBorBottom,
  909.                 WA_MaxHeight,        Window -> WScreen -> Height,
  910.  
  911.                 WA_Title,        LocaleString(MSG_FASTMACROS_FAST_MACROS_TXT),
  912.  
  913.                 WA_NewLookMenus,    TRUE,
  914.                 WA_Gadgets,        Scroller,
  915.  
  916.                 WA_CustomScreen,    Window -> WScreen,
  917.  
  918.                 AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  919.                 CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  920.             TAG_DONE))
  921.             {
  922.                 ButtonTop    = 0;
  923.                 ButtonCount    = -1;
  924.  
  925.                 FastWindow -> UserPort = Window -> UserPort;
  926.  
  927.                 ModifyIDCMP(FastWindow,Window -> IDCMPFlags | IDCMP_IDCMPUPDATE | IDCMP_SIZEVERIFY);
  928.  
  929.                 SetMenuStrip(FastWindow,Menu);
  930.  
  931.                 FastWindow -> Flags &= ~WFLG_RMBTRAP;
  932.  
  933.                 RefreshFastWindow(TRUE);
  934.  
  935.                 CheckItem(MEN_FAST_MACROS_WINDOW,TRUE);
  936.  
  937.                 return(TRUE);
  938.             }
  939.  
  940.             FastDeleteScroller();
  941.         }
  942.  
  943.         FreeButtonClass();
  944.     }
  945.  
  946.     return(FALSE);
  947. }
  948.  
  949.     /* HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID):
  950.      *
  951.      *    Process fast! macro window input.
  952.      */
  953.  
  954. VOID __regargs
  955. HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID)
  956. {
  957.     STATIC BYTE Scrolling = FALSE;
  958.  
  959.     switch(IClass)
  960.     {
  961.         case IDCMP_GADGETUP:
  962.  
  963.             if(GadgetID == GAD_SCROLLER)
  964.                 Scrolling = FALSE;
  965.             else
  966.             {
  967.                 if(GadgetID < GAD_SCROLLER && !ICode)
  968.                 {
  969.                     struct MacroNode *Node;
  970.  
  971.                     if(Node = (struct MacroNode *)GetListNode(GadgetID + ButtonTop,&FastMacroList))
  972.                     {
  973.                         if(Node -> mn_Code[0])
  974.                             SerialCommand(Node -> mn_Code);
  975.                     }
  976.                 }
  977.             }
  978.  
  979.             break;
  980.  
  981.         case IDCMP_GADGETDOWN:
  982.  
  983.             if(GadgetID == GAD_SCROLLER)
  984.             {
  985.                 Scrolling = TRUE;
  986.  
  987.                 RefreshFastWindow(FALSE);
  988.             }
  989.  
  990.             break;
  991.  
  992.         case IDCMP_MOUSEMOVE:
  993.  
  994.             if(Scrolling)
  995.                 RefreshFastWindow(FALSE);
  996.  
  997.             break;
  998.  
  999.         case IDCMP_IDCMPUPDATE:
  1000.  
  1001.             switch(GadgetID)
  1002.             {
  1003.                 case GAD_UP:    if(ButtonTop)
  1004.                         {
  1005.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1006.                                 PGA_Top,ButtonTop - 1,
  1007.                             TAG_DONE);
  1008.  
  1009.                             RefreshFastWindow(FALSE);
  1010.                         }
  1011.  
  1012.                         break;
  1013.  
  1014.                 case GAD_DOWN:    if(ButtonTop + ButtonCount < FastMacroCount)
  1015.                         {
  1016.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1017.                                 PGA_Top,ButtonTop + 1,
  1018.                             TAG_DONE);
  1019.  
  1020.                             RefreshFastWindow(FALSE);
  1021.                         }
  1022.  
  1023.                         break;
  1024.             }
  1025.  
  1026.             break;
  1027.     }
  1028. }
  1029.